//-------------------------------------------------------------------------------------------------
// HD61202 low-level driver for PIC16 MCU (PICC Lite compiler)
// http://en.radzio.dxp.pl/ks0108/
// (c) Rados�aw Kwiecie�, radek@dxp.pl
//-------------------------------------------------------------------------------------------------

#include "p18f4520.h"
#include "string.h"
#include "delays.h"
//__CONFIG(WDTDIS & HS & UNPROTECT);

#define HD61202_DATA_PORT	PORTD
#define HD61202_DATA_DIR	TRISD
#define HD61202_DATA_PIN	PORTD

#define HD61202_CTRL_PORT	PORTB
#define HD61202_CTRL_DIR	TRISB

#define HD61202_DI			(1)
#define HD61202_RW			(1 << 1)
#define HD61202_EN			(1 << 2)

#define HD61202_CS1			(1 << 3)
#define HD61202_CS2			(1 << 4)

void HD61202_CS3_on(void){PORTCbits.RC1 = 1;}
void HD61202_CS3_off(void){PORTCbits.RC1 = 0;}
void HD61202_CS3_dir(void){TRISCbits.TRISC1 = 0;}

// todo: set timer at submission of each command, 
// wait for timer at beginning of next command

#define DISPLAY_STATUS_BUSY 0x80
#ifndef __DEBUG
#define careBusy		// define this to use busy flag.
				// otherwise, just wait 4ms
#endif

extern unsigned char screen_x, screen_y;
//-------------------------------------------------------------------------------------------------
// Delay function
//-------------------------------------------------------------------------------------------------
void GLCD_Delay(void)
{
_asm nop _endasm	// at least 500 ns delay
_asm nop _endasm
_asm nop _endasm
_asm nop _endasm
_asm nop _endasm
_asm nop _endasm
}
//-------------------------------------------------------------------------------------------------
//
//-------------------------------------------------------------------------------------------------
void GLCD_Delay4ms(void){Delay10KTCYx(4);}// 4ms, like in example code
//-------------------------------------------------------------------------------------------------
//
//-------------------------------------------------------------------------------------------------
void GLCD_InitializePorts(void)
{
HD61202_CTRL_PORT |= (HD61202_CS1 | HD61202_CS2); // | HD61202_CS3);
HD61202_CTRL_DIR &= ~(HD61202_CS1 | HD61202_CS2 | HD61202_DI | HD61202_RW | HD61202_EN); // | HD61202_CS3
HD61202_CS3_dir();
HD61202_CS3_off();
}
//-------------------------------------------------------------------------------------------------
// Enable Controller (0-1)
//-------------------------------------------------------------------------------------------------
void GLCD_EnableController(unsigned char controller)
{
	HD61202_CS3_on();
	switch(controller){
		case 0 : HD61202_CTRL_PORT &= ~HD61202_CS1; break;
		case 1 : HD61202_CTRL_PORT &= ~HD61202_CS2; break;
	}
}
//-------------------------------------------------------------------------------------------------
// Disable Controller (0-1)
//-------------------------------------------------------------------------------------------------
void GLCD_DisableController(unsigned char controller)
{
	switch(controller){
		case 0 : HD61202_CTRL_PORT |= HD61202_CS1; break;
		case 1 : HD61202_CTRL_PORT |= HD61202_CS2; break;
	}
	HD61202_CS3_off();
}
//-------------------------------------------------------------------------------------------------
// Read Status from specified controller (0-2)
//-------------------------------------------------------------------------------------------------
unsigned char GLCD_ReadStatus(unsigned char controller)
{
unsigned char status;
HD61202_DATA_DIR = 0xFF;
HD61202_CTRL_PORT |= HD61202_RW;
HD61202_CTRL_PORT &= ~HD61202_DI;
GLCD_EnableController(controller);
HD61202_CTRL_PORT |= HD61202_EN;
GLCD_Delay();
status = HD61202_DATA_PIN;
HD61202_CTRL_PORT &= ~HD61202_EN;
GLCD_DisableController(controller);
return status;
}
//-------------------------------------------------------------------------------------------------
// Write command to specified controller
//-------------------------------------------------------------------------------------------------
void GLCD_WriteCommand(unsigned char commandToWrite, unsigned char controller)
{
#ifdef careBusy
while(GLCD_ReadStatus(controller)&DISPLAY_STATUS_BUSY);
#else
GLCD_Delay4ms(); // todo: move this to an appropriate place
#endif
HD61202_DATA_DIR = 0x00;
HD61202_CTRL_PORT &= ~(HD61202_RW | HD61202_DI);
GLCD_EnableController(controller);
HD61202_DATA_PORT = commandToWrite;
_asm nop _endasm
_asm nop _endasm
HD61202_CTRL_PORT |= HD61202_EN;
GLCD_Delay();
HD61202_CTRL_PORT &= ~HD61202_EN;
GLCD_DisableController(controller);
}
//-------------------------------------------------------------------------------------------------
// Read data from current position
//-------------------------------------------------------------------------------------------------
unsigned char GLCD_ReadData(void)
{
unsigned char data;
#ifdef careBusy
while(GLCD_ReadStatus(screen_x / 64)&DISPLAY_STATUS_BUSY);
#else
GLCD_Delay4ms();
#endif
HD61202_DATA_DIR = 0xFF;
HD61202_CTRL_PORT |= (HD61202_RW | HD61202_DI);
GLCD_EnableController(screen_x / 64);
_asm nop _endasm
_asm nop _endasm
HD61202_CTRL_PORT |= HD61202_EN;
GLCD_Delay();
data = HD61202_DATA_PIN;
HD61202_CTRL_PORT &= ~HD61202_EN;
GLCD_DisableController(screen_x / 64);
screen_x++;
return data;
}
//-------------------------------------------------------------------------------------------------
// Write data to current position
//-------------------------------------------------------------------------------------------------
void GLCD_WriteData(unsigned char dataToWrite)
{
#ifdef careBusy
while(GLCD_ReadStatus(screen_x / 64)&DISPLAY_STATUS_BUSY);
#else
GLCD_Delay4ms();
#endif
HD61202_DATA_DIR = 0x00;
HD61202_CTRL_PORT &= ~HD61202_RW;
HD61202_CTRL_PORT |= HD61202_DI;
HD61202_DATA_PORT = dataToWrite;

GLCD_EnableController(screen_x / 64);
_asm nop _endasm
_asm nop _endasm
HD61202_CTRL_PORT |= HD61202_EN;
GLCD_Delay();
HD61202_CTRL_PORT &= ~HD61202_EN;
GLCD_DisableController(screen_x / 64);
screen_x++;
}
//-------------------------------------------------------------------------------------------------
//
//-------------------------------------------------------------------------------------------------
unsigned char GLCD_ReadByteFromROMMemory(rom char * romPtr)
{
	char tmpChar;
//void *memcpypgm2ram (auto void *s1, auto const MEM_MODEL rom void *s2, auto sizeram_t n);
	memcpypgm2ram(&tmpChar, romPtr, 1);
	return tmpChar;
}
//-------------------------------------------------------------------------------------------------
//
//-------------------------------------------------------------------------------------------------
